﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Xml.Linq;

////
/*
f
 *Using System.IO added to this file by Amir Pouya;
 * e.Message(); ارور داشت کامنتش کردم

 * جان هرکی دوس دارین کد اشکال دار چک این نکنید باعث میشه کل پروژه کامپایل نشه


*/
////


namespace Paltop_.Controllers
{
    public enum SortType { ByTitle, BySize }
    public enum Sort { Ascending, Descending }
    public class FileManagerController
    {
        //private Paltop_DatabaseLayer.PaltopDatabaseEntities GlobalPde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
        public XElement GetFileAndFolderList(int userID, bool isRoot, Paltop_.Controllers.Sort sort)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            System.Linq.IQueryable<Paltop_DatabaseLayer.FileAndFolder_View> temp;
            if (sort == Paltop_.Controllers.Sort.Ascending)
                temp = from F in pde.FileAndFolder_View
                       where F.AccountID == userID && F.IsRoot == isRoot
                       orderby F.Title ascending
                       select F;
            else
                temp = from F in pde.FileAndFolder_View
                       where F.AccountID == userID && F.IsRoot == isRoot
                       orderby F.Title descending
                       select F;
            XElement fileList = new XElement("FileAndFoldersInfoList");
            foreach (var item in temp)
            {
                fileList.Add(ConvertFileInfoXml(item));
            }
            return fileList;
        }
        public XElement GetFileAndFolderList(int userID, bool isRoot, Paltop_.Controllers.Sort sort, Paltop_.Controllers.SortType sortType)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            System.Linq.IQueryable<Paltop_DatabaseLayer.FileAndFolder_View> temp;
            if (sortType == Paltop_.Controllers.SortType.ByTitle)
            {
                if (sort == Paltop_.Controllers.Sort.Ascending)
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.IsRoot == isRoot
                           orderby F.Title ascending
                           select F;
                else
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.IsRoot == isRoot
                           orderby F.Title descending
                           select F;
            }
            else
            {
                if (sort == Paltop_.Controllers.Sort.Ascending)
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.IsRoot == isRoot
                           orderby F.Size ascending
                           select F;
                else
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.IsRoot == isRoot
                           orderby F.Size descending
                           select F;
            }
            XElement fileList = new XElement("FileAndFoldersInfoList");
            foreach (var item in temp)
            {
                fileList.Add(ConvertFileInfoXml(item));
            }
            return fileList;
        }
        public XElement GetFileAndFolderList(int userID, int parentId, Paltop_.Controllers.Sort sort, Paltop_.Controllers.SortType sortType)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            System.Linq.IQueryable<Paltop_DatabaseLayer.FileAndFolder_View> temp;
            if (sortType == Paltop_.Controllers.SortType.ByTitle)
            {
                if (sort == Paltop_.Controllers.Sort.Ascending)
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.ParentID == parentId
                           orderby F.Title ascending
                           select F;
                else
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.ParentID == parentId
                           orderby F.Title descending
                           select F;
            }
            else
            {
                if (sort == Paltop_.Controllers.Sort.Ascending)
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.ParentID == parentId
                           orderby F.Size ascending
                           select F;
                else
                    temp = from F in pde.FileAndFolder_View
                           where F.AccountID == userID && F.ParentID == parentId
                           orderby F.Size descending
                           select F;
            }
            XElement fileList = new XElement("FileAndFoldersInfoList");
            foreach (var item in temp)
            {
                fileList.Add(ConvertFileInfoXml(item));
            }
            return fileList;
        }
        public XElement GetFileOrFolderInfo(int userID, int fileInfoID)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();

            Paltop_DatabaseLayer.FileAndFolder_View temp = (from F in pde.FileAndFolder_View
                                                            where F.AccountID == userID && F.FileInfoID == fileInfoID
                                                            select F).Single();
            return ConvertFileInfoXml(temp);
        }
        public int CopyPaste(int userID, int sourceFileOrFolderID, int DestinationFoderID, bool file)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities Pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var b = Pde.FileAndFolder_View.Where(p => p.AccountID == userID && p.FileInfoID == sourceFileOrFolderID);
            var source = b.First();
            string destAddress = "";
            string sourceAddress = "";
            Paltop_DatabaseLayer.FileInfo destination = CopyHelper(userID, DestinationFoderID, source, ref destAddress, ref sourceAddress);
            try
            {
                copyPastOnDisk(sourceAddress, destAddress, source.Title, destination.Title, file);
            }
            catch (Exception)
            {

                //copy is not working for files
            }
            {
                Paltop_DatabaseLayer.FileInfo tempDest = new Paltop_DatabaseLayer.FileInfo();
                tempDest.Address = destination.Address;
                tempDest.CreationDate = destination.CreationDate;
                tempDest.FileExtentionID = destination.FileExtentionID;
                tempDest.FileFlag = destination.FileFlag;
                tempDest.FileSecurityInfoes.Add(Pde.FileSecurityInfoes.Where(fs => fs.FileSecurityInfoID == source.FileSecurityInfoID && fs.AccountID == userID).First());
                tempDest.IsRoot = destination.IsRoot;
                tempDest.ParentID = destination.ParentID;
                tempDest.RootFolderID = destination.RootFolderID;
                tempDest.Size = destination.Size;
                tempDest.Title = destination.Title;

                Pde.FileInfoes.AddObject(tempDest);
                if (file)
                {
                    Pde.SaveChanges();
                    AlterParentSize(DestinationFoderID, tempDest.Size.Value);
                    AlterSizePde.SaveChanges();
                    return tempDest.FileInfoID;
                }
                else
                {
                    if (DestinationFoderID != 0)
                    {
                        var newParent = Pde.FileInfoes.Where(p => p.FileInfoID == DestinationFoderID).First();
                        newParent.Size += destination.Size;
                    }
                    Pde.SaveChanges();
                    //disconnectedFileInfo.Add(destination);
                    //disconnectedFileInfo.Add(pde.FileInfoes.Where(F=> F.FileInfoID==source.FileInfoID).First());
                    if (copyChildrenToNewParent(source.FileInfoID, tempDest.FileInfoID, userID))
                    {
                        Pde.SaveChanges();
                        AlterParentSize(DestinationFoderID, tempDest.Size.Value);
                        AlterSizePde.SaveChanges();
                        return tempDest.FileInfoID;
                    }
                    return 0;
                }



            }
            //else
            //    return 0;

        }
        public bool CutPaste(int userID, int sourceFileOrFolderID, int DestinationFoderID, bool file)
        {
            if (sourceFileOrFolderID == DestinationFoderID)
                return false;
            Paltop_DatabaseLayer.PaltopDatabaseEntities Pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var b = Pde.FileAndFolder_View.Where(p => p.AccountID == userID && p.FileInfoID == sourceFileOrFolderID);
            if (b.Count() > 0)
            {

                var source = (from F in Pde.FileInfoes
                              where F.FileInfoID == sourceFileOrFolderID
                              select F).Single();
                if (DestinationFoderID != 0)
                {
                    var oldParentchile = from F in Pde.FileInfoes
                                         where F.ParentID == DestinationFoderID && F.Title == source.Title
                                         select F;
                    if (oldParentchile.Count() == 0)
                    {
                        var destionation = (from F in Pde.FileInfoes
                                            where F.FileInfoID == DestinationFoderID
                                            select F).Single();
                        source.ParentID = DestinationFoderID;
                        //source.Address = (destionation.Address == "" ? "" : destionation.Address + "\\") + destionation.Title;
                        source.IsRoot = false;
                        destionation.Size += source.Size;
                    }
                    else
                        throw new Exception("#The distination already contains a " + (file ? "file" : "folder") + " named " + source.Title);
                }
                else
                {
                    var oldParentchile = from F in Pde.FileAndFolder_View
                                         where F.AccountID == userID && F.IsRoot == true && F.Title == source.Title
                                         select F;
                    if (oldParentchile.Count() == 0)
                    {
                        source.ParentID = 0;
                        //source.Address = "";
                        source.IsRoot = true;
                    }
                    else
                        throw new Exception("#The distination already contains a " + (file ? "file" : "folder") + " named " + source.Title);
                }

                if (!file)
                {
                    if (!DestinationCheck(DestinationFoderID, sourceFileOrFolderID))
                        throw new Exception("#The distination folder is a subfolder of the source folder");
                    //if (CutHelper(source.FileInfoID, source.Address, source.Title))
                    //{

                    //    CutPde.SaveChanges();
                    //}
                    //else
                    //    status = false;

                }

                Pde.SaveChanges();
                AlterParentSize(DestinationFoderID, source.Size.Value);
                AlterParentSize(source.ParentID.Value, -source.Size.Value);
                AlterSizePde.SaveChanges();
                return true;

            }
            return false;

        }
        Paltop_DatabaseLayer.PaltopDatabaseEntities CutPde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
        ///// <summary>
        ///// recursivliy alter all the children address for cut operation
        ///// </summary>
        ///// <param name="FileOrFolderID">source</param>
        ///// <param name="addresss">new address</param>
        ///// <param name="parentTitle">source title</param>
        ///// <returns></returns>
        //private bool CutHelper(int FileOrFolderID,string addresss,string parentTitle)
        //{
        //    var children = from F in CutPde.FileInfoes
        //                   where F.ParentID == FileOrFolderID
        //                   select F;
        //    bool status = true;
        //    foreach (var item in children)
        //    {
        //        item.Address = addresss + "\\" + parentTitle;
        //        if(!item.FileFlag)
        //            status= CutHelper(item.FileInfoID, item.Address, item.Title);

        //    }
        //    return status;

        //}
        /// <summary>
        /// this method check to see if the destination folder is a sub folder of source folder or not
        /// and returns true if it's not ;
        /// </summary>
        /// <param name="id">destination</param>
        /// <param name="checkId">source</param>
        /// <returns>bool</returns>
        private bool DestinationCheck(int id, int checkId)
        {
            if (id == 0)
                return true;
            var parent = (from F in CutPde.FileInfoes
                          where F.FileInfoID == id
                          select F).Single();
            if (parent.ParentID == 0)
                return true;
            else if (parent.ParentID == checkId)
                return false;
            else
                return DestinationCheck(parent.ParentID.Value, checkId);
        }
        private Paltop_DatabaseLayer.FileInfo CopyHelper(int userID, int DestinationFoderID, Paltop_DatabaseLayer.FileAndFolder_View source, ref string destAddress, ref string sourceAddress)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities Pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            Paltop_DatabaseLayer.FileInfo destination = new Paltop_DatabaseLayer.FileInfo();
            if (DestinationFoderID != 0)
            {
                var newParent = Pde.FileInfoes.Where(p => p.FileInfoID == DestinationFoderID).First();

                destAddress = HttpRuntime.AppDomainAppPath + "fileManager\\" + userID + "" + newParent.Address + "\\" + newParent.Title;

                destination.FileSecurityInfoes.Add(newParent.FileSecurityInfoes.Where(p => p.AccountID == userID && p.Access == "RW").First());
                destination.Address = newParent.Address + "\\" + newParent.Title;
                destination.IsRoot = false;
                destination.ParentID = newParent.FileInfoID;
                var newParentChildren = Pde.FileInfoes.Where(F => (F.Title == source.Title || F.Title.Contains(source.Title + "_Copy(")) && F.ParentID == DestinationFoderID).Count();
                destination.Title = (newParentChildren > 0 ? source.Title + "_Copy(" + newParentChildren + ")" : source.Title);
            }
            else
            {
                destAddress = HttpRuntime.AppDomainAppPath + "fileManager\\" + userID;
                Paltop_DatabaseLayer.FileSecurityInfo fsecurity = new Paltop_DatabaseLayer.FileSecurityInfo();
                fsecurity.AccountID = userID;
                fsecurity.Access = source.Access;
                destination.Address = "";
                destination.IsRoot = true;
                destination.ParentID = 0;
                destination.FileSecurityInfoes.Add(fsecurity);
                var newParentChildren = Pde.FileInfoes.Where(F => (F.Title == source.Title || F.Title.Contains(source.Title + "_Copy(")) && F.ParentID == DestinationFoderID).Count();
                destination.Title = (newParentChildren > 0 ? source.Title + "_Copy(" + newParentChildren + ")" : source.Title);
            }
            sourceAddress = HttpRuntime.AppDomainAppPath + "fileManager\\" + userID + "" + source.Address;
            destination.CreationDate = source.CreationDate;
            destination.FileExtentionID = source.FileExtentionID;
            destination.FileFlag = source.FileFlag.Value;
            destination.Size = source.Size;


            destination.RootFolderID = 0;
            return destination;
        }
        /// <summary>
        /// converts all the propery of file info object to element of an xml variable
        /// </summary>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        private XElement ConvertFileInfoXml(Paltop_DatabaseLayer.FileInfo fileInfo)
        {
            XElement fileInfoXml = new XElement("FileAndFolderInfo");
            XElement temp = new XElement("Address");
            temp.Value = fileInfo.Address;
            fileInfoXml.Add(temp);
            temp = new XElement("Address");
            temp.Value = fileInfo.Address;
            fileInfoXml.Add(temp);
            temp = new XElement("CreationDate");
            temp.Value = fileInfo.CreationDate.Value.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileExtentionID");
            temp.Value = fileInfo.FileExtentionID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileFlag");
            temp.Value = fileInfo.FileFlag.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileInfoID");
            temp.Value = fileInfo.FileInfoID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("IsRoot");
            temp.Value = fileInfo.IsRoot.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("ParentID");
            temp.Value = fileInfo.ParentID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("RootFolderID");
            temp.Value = fileInfo.RootFolderID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Size");
            temp.Value = fileInfo.Size.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Title");
            temp.Value = fileInfo.Title.ToString();
            fileInfoXml.Add(temp);
            return fileInfoXml;

        }
        private XElement ConvertFileInfoXml(Paltop_DatabaseLayer.FileAndFolder_View fileInfo)
        {
            XElement fileInfoXml = new XElement("FileAndFolderInfo");
            XElement temp = new XElement("Address");
            temp.Value = fileInfo.Address;
            fileInfoXml.Add(temp);
            temp = new XElement("Address");
            temp.Value = fileInfo.Address;
            fileInfoXml.Add(temp);
            temp = new XElement("CreationDate");
            temp.Value = fileInfo.CreationDate.Value.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileExtentionID");
            temp.Value = fileInfo.FileExtentionID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileFlag");
            temp.Value = fileInfo.FileFlag.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileInfoID");
            temp.Value = fileInfo.FileInfoID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("IsRoot");
            temp.Value = fileInfo.IsRoot.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("ParentID");
            temp.Value = fileInfo.ParentID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("RootFolderID");
            temp.Value = fileInfo.RootFolderID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Size");
            temp.Value = fileInfo.Size.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Title");
            temp.Value = fileInfo.Title.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Access");
            temp.Value = fileInfo.Access.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("AccountID");
            temp.Value = fileInfo.AccountID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("Description");
            temp.Value = (fileInfo.Description == null ? "" : fileInfo.Description.ToString());
            fileInfoXml.Add(temp);
            temp = new XElement("ExtentionTitle");
            temp.Value = fileInfo.ExtentionTitle.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("FileSecurityInfoID");
            temp.Value = fileInfo.FileSecurityInfoID.ToString();
            fileInfoXml.Add(temp);
            temp = new XElement("JSFunction");
            temp.Value = fileInfo.JSFunction.ToString();
            fileInfoXml.Add(temp);
            return fileInfoXml;
        }
        private bool copyChildrenToNewParent(int oldParent, int newParent, int userID)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var children = from F in pde.FileAndFolder_View
                           where F.ParentID == oldParent
                           select F;

            bool successSatus = false;
            string destStr = "", sorceStr = "";
            List<Paltop_DatabaseLayer.FileInfo> destChilderen = new List<Paltop_DatabaseLayer.FileInfo>();
            //Dictionary<string, int> destChilderen = new Dictionary<string, int>();
            foreach (var item in children)
            {
                Paltop_DatabaseLayer.FileInfo tempDest = new Paltop_DatabaseLayer.FileInfo();
                Paltop_DatabaseLayer.FileInfo dest = CopyHelper(userID, newParent, item, ref destStr, ref sorceStr);
                tempDest.Address = dest.Address;
                tempDest.CreationDate = dest.CreationDate;
                tempDest.FileExtentionID = dest.FileExtentionID;
                tempDest.FileFlag = dest.FileFlag;
                tempDest.FileSecurityInfoes.Add(pde.FileSecurityInfoes.Where(fs => fs.FileSecurityInfoID == item.FileSecurityInfoID && fs.AccountID == userID).First());
                tempDest.IsRoot = dest.IsRoot;
                tempDest.ParentID = dest.ParentID;
                tempDest.RootFolderID = dest.RootFolderID;
                tempDest.Size = dest.Size;
                tempDest.Title = dest.Title;

                pde.FileInfoes.AddObject(tempDest);
                destChilderen.Add(tempDest);
            }
            if (destChilderen.Count != 0)
            {
                pde.SaveChanges();
                //for (int i = 0; i < destChilderen.Count; i++)
                //{
                //    string title=destChilderen.ElementAt(i).Title;
                //    destChilderen.ElementAt(i).FileInfoID = pde.FileInfoes.Where(F => F.ParentID == newParent && F.Title ==title ).First().FileInfoID;
                //}
                foreach (var item in children)
                {

                    successSatus = copyChildrenToNewParent(item.FileInfoID, destChilderen.Find(p => p.Title == item.Title).FileInfoID, userID);


                }
                return successSatus;
            }
            else
                return true;


        }
        public string CreateNewFolder(int userId, int pid, string name)
        {
            string address = "";
            bool access = false;
            int rootId = 0;
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            if (pid == 0)
                access = true;
            else
            {
                var folderInfo = from F in pde.FileAndFolder_View
                                 where F.AccountID == userId && F.Access == "RW" && F.FileInfoID == pid
                                 select F;
                if (folderInfo.Count() != 0)
                {
                    access = true;
                    address = folderInfo.First().Address + "\\" + folderInfo.First().Title;
                    rootId = folderInfo.First().RootFolderID.Value;
                }
            }
            if (access)
            {
                string realAddres = HttpRuntime.AppDomainAppPath + "fileManager\\" + userId + "\\" + address + "\\" + name;
                realAddres.Replace("/", "\\");
                if (!Directory.Exists(realAddres))
                    Directory.CreateDirectory(realAddres);
                else
                {
                    return "The destination already contains a folder named '" + name + "'";
                }
                var extentions = from E in pde.FileExtentions
                                 where E.Title == "link"
                                 select E;

                Paltop_DatabaseLayer.FileInfo fi = new Paltop_DatabaseLayer.FileInfo();
                fi.Address = address;
                fi.CreationDate = DateTime.Now;

                fi.FileFlag = false;
                fi.IsRoot = (pid == 0 ? true : false);
                fi.ParentID = pid;
                fi.RootFolderID = rootId;
                fi.Size = 0;
                fi.Title = name;
                if (extentions.Count() != 0)
                {
                    fi.FileExtentionID = extentions.First().FileExtentionID;
                }
                else
                {
                    Paltop_DatabaseLayer.FileExtention fe = new Paltop_DatabaseLayer.FileExtention();
                    fe.Title = "link";
                    fe.JSFunction = "OpenFolder(this.id)";
                    pde.FileExtentions.AddObject(fe);
                    pde.SaveChanges();
                    fi.FileExtentionID = fe.FileExtentionID;
                }
                Paltop_DatabaseLayer.FileSecurityInfo fsi = new Paltop_DatabaseLayer.FileSecurityInfo();
                fsi.Access = "RW";
                fsi.AccountID = userId;
                fi.FileSecurityInfoes.Add(fsi);
                pde.FileInfoes.AddObject(fi);
                pde.SaveChanges();
                var retFolderInfo = (from F in pde.FileAndFolder_View
                                     where F.FileInfoID == fi.FileInfoID
                                     select F).Single();
                string retVal = "{";
                retVal += "\"Title\":\"" + retFolderInfo.Title + "\",";
                retVal += "\"FileInfoID\":\"" + retFolderInfo.FileInfoID + "\",";
                retVal += "\"ExtentionTitle\":\"" + retFolderInfo.ExtentionTitle + "\",";
                retVal += "\"JSFunction\":\"" + retFolderInfo.JSFunction + "\"}";
                return "ok$" + retVal;
            }
            else
                return "Access denied!";
        }
        private int CreateNewFolderInside(int userId, int pid, string name)
        {
            string address = "";
            int rootId = 0;
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            if (pid != 0)
            {
                var parent = (from P in pde.FileInfoes
                              where P.FileInfoID == pid
                              select P).Single();
                address = parent.Address + "//" + parent.Title;
            }
            var beforFolders = from F in pde.FileInfoes
                               where F.ParentID == pid && F.Title == name
                               select F;
            if (beforFolders.Count() > 0)
                return beforFolders.First().FileInfoID;
            var extentions = from E in pde.FileExtentions
                             where E.Title == "link"
                             select E;

            Paltop_DatabaseLayer.FileInfo fi = new Paltop_DatabaseLayer.FileInfo();
            fi.Address = address;
            fi.CreationDate = DateTime.Now;

            fi.FileFlag = false;
            fi.IsRoot = (pid == 0 ? true : false);
            fi.ParentID = pid;
            fi.RootFolderID = rootId;
            fi.Size = 0;
            fi.Title = name;
            if (extentions.Count() != 0)
            {
                fi.FileExtentionID = extentions.First().FileExtentionID;
            }
            else
            {
                Paltop_DatabaseLayer.FileExtention fe = new Paltop_DatabaseLayer.FileExtention();
                fe.Title = "link";
                fe.JSFunction = "OpenFolder(this.id)";
                pde.FileExtentions.AddObject(fe);
                pde.SaveChanges();
                fi.FileExtentionID = fe.FileExtentionID;
            }
            Paltop_DatabaseLayer.FileSecurityInfo fsi = new Paltop_DatabaseLayer.FileSecurityInfo();
            fsi.Access = "RW";
            fsi.AccountID = userId;
            fi.FileSecurityInfoes.Add(fsi);
            pde.FileInfoes.AddObject(fi);
            pde.SaveChanges();
            return fi.FileInfoID;

        }
        /// <summary>
        /// adds the file info to database by RW access
        /// example:controller.AddFile(userID, "test.png", "png", DestinationId, 20);
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="title"></param>
        /// <param name="ExtentionTiltle"></param>
        /// <param name="parentId"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public bool AddFile(int userID, string title, string ExtentionTiltle, int parentId, int size)
        {
            ExtentionTiltle = ExtentionTiltle.ToLower();

            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            string Address = "";
            try
            {
                if (parentId > 0)
                {
                    var parentInfo = (from F in pde.FileAndFolder_View
                                      where F.FileInfoID == parentId && F.AccountID == userID
                                      select F).Single();
                    Address = parentInfo.Address + "\\" + parentInfo.Title;
                }

            }
            catch (Exception)
            {

                throw new Exception("#Access denied!");
            }
            int extentionId = 0;
            var beforFiles = from F in pde.FileInfoes
                             where F.ParentID == parentId && F.Title == title
                             select F;
            if (beforFiles.Count() > 0)
                return true;
            try
            {

                var extentionInfo = from S in pde.FileExtentions
                                    where S.Title == ExtentionTiltle
                                    select S;

                if (extentionInfo.Count() != 0)
                {
                    extentionId = extentionInfo.First().FileExtentionID;

                }
                else
                {
                    var extentionSetting = (from S in pde.SYSMainSettings
                                            where S.Title == "Extentions"
                                            select S).Single();
                    XElement setting = XElement.Parse(extentionSetting.Setting);
                    var extInfo = from E in setting.Elements("Extention")
                                  where E.Element("Title").Value == ExtentionTiltle
                                  select E;
                    if (extInfo.Count() > 0)
                    {
                        Paltop_DatabaseLayer.FileExtention fe = new Paltop_DatabaseLayer.FileExtention();
                        fe.JSFunction = extInfo.First().Element("JSFunction").Value;
                        fe.Title = ExtentionTiltle;
                        pde.FileExtentions.AddObject(fe);
                        pde.SaveChanges();
                        extentionId = fe.FileExtentionID;
                    }
                    else
                    {

                        Paltop_DatabaseLayer.FileExtention fe = new Paltop_DatabaseLayer.FileExtention();
                        fe.Description = "NOT SUPPORTED";
                        fe.JSFunction = "downloadUnknownType(this.id)";
                        fe.Title = ExtentionTiltle;
                        pde.FileExtentions.AddObject(fe);
                        pde.SaveChanges();
                        extentionId = fe.FileExtentionID;
                    }

                }


            }
            catch (Exception)
            {
                throw new Exception("#Error in extention difination!");
            }
            Paltop_DatabaseLayer.FileInfo fileInfo = new Paltop_DatabaseLayer.FileInfo();
            fileInfo.Address = Address;
            fileInfo.CreationDate = DateTime.Now;
            fileInfo.FileExtentionID = extentionId;
            fileInfo.FileFlag = true;
            Paltop_DatabaseLayer.FileSecurityInfo fsecurity = new Paltop_DatabaseLayer.FileSecurityInfo();
            fsecurity.Access = "RW";
            fsecurity.AccountID = userID;
            pde.FileSecurityInfoes.AddObject(fsecurity);
            pde.SaveChanges();
            fileInfo.FileSecurityInfoes.Add(fsecurity);
            fileInfo.IsRoot = (parentId == 0 ? true : false);
            fileInfo.ParentID = parentId;
            fileInfo.RootFolderID = 0;
            fileInfo.Size = size;
            fileInfo.Title = title;
            pde.FileInfoes.AddObject(fileInfo);
            pde.SaveChanges();
            AlterParentSize(parentId, size);
            AlterSizePde.SaveChanges();
            return true;
        }
        public string GetFile(int userID, int fileID)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var temp = (from F in pde.FileAndFolder_View
                        where F.AccountID == userID && F.FileInfoID == fileID
                        select F).Single();
            string tempAddress = HttpRuntime.AppDomainAppPath + "fileManager\\" + userID + "\\" + (temp.ParentID == 0 ? "" : temp.Address + "\\") + temp.Title;
            return tempAddress;


        }
        public bool DeleteFileOrFolder(int fileInfoID, int userID, bool file)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var b = pde.FileAndFolder_View.Where(p => p.FileInfoID == fileInfoID && p.AccountID == userID && p.Access == "RW");
            try
            {
                deleteFromDisk(HttpRuntime.AppDomainAppPath + "fileManager\\" + userID + "\\" + b.First().Address, b.First().Title, file);
            }
            catch (Exception)
            {

            }
            AlterParentSize(b.First().ParentID.Value, -b.First().Size.Value);
            AlterSizePde.SaveChanges();
            return DeleteFileOrFolderRecursive(fileInfoID, userID);
        }
        private bool DeleteFileOrFolderRecursive(int fileInfoID, int userID)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var b = pde.FileAndFolder_View.Where(p => p.FileInfoID == fileInfoID && p.AccountID == userID && p.Access == "RW");
            bool returnVal = true;
            var source = b.FirstOrDefault();
            {
                var child = pde.FileAndFolder_View.Where(p => p.ParentID == source.FileInfoID && p.AccountID == userID && p.Access == "RW");
                var childList = child.ToList();

                for (int i = 0; i < childList.Count; i++)
                {

                    try
                    {
                        returnVal = DeleteFileOrFolderRecursive(childList.ElementAt(i).FileInfoID, userID);

                    }
                    catch (Exception ve)
                    {

                        continue;
                    }
                }
                if (returnVal)
                {
                    var sourseReal = (from F in pde.FileInfoes
                                      where F.FileInfoID == fileInfoID
                                      select F).First();
                    var sourceSecurityList = sourseReal.FileSecurityInfoes.Where(p => p.AccountID == userID).ToList();
                    for (int i = 0; i < sourceSecurityList.Count; i++)
                    {
                        pde.DeleteSecurityInfo(sourseReal.FileInfoID, sourceSecurityList.ElementAt(i).FileSecurityInfoID);
                    }
                    pde.SaveChanges();
                    // pde.Refresh(System.Data.Objects.RefreshMode.StoreWins, pde.FileInfoes);

                    //pde.FileInfoes.DeleteObject(sourseReal);
                    //pde.SaveChanges();
                }

            }

            return returnVal;

        }
        public string treeView(int userId, Stack<int> openPath)
        {
            string retVal = "{\"Item\":\"Root\",";
            retVal += "\"Class\":\"open\",";
            retVal += "\"Type\":\"folder\",";
            retVal += "\"FileInfoId\":\"treeNode_0\",";
            string child = "";
            var Children = from F in GlobalPdeReader.FileAndFolder_View
                           where F.ParentID == 0 && F.AccountID == userId && F.IsRoot == true
                           select F;
            bool first = true;
            openPath.Pop();
            foreach (var item in Children)
            {
                if (first)
                {
                    child += treeViewRecursiv(item.FileInfoID, openPath);
                    first = false;
                }
                else
                    child += "," + treeViewRecursiv(item.FileInfoID, openPath);
            }
            if (child == "")
                retVal += "\"ChildItems\":\"\"}";
            else
                retVal += "\"ChildItems\":[" + child + "]}";
            return retVal;
        }
        private Paltop_DatabaseLayer.PaltopDatabaseEntities GlobalPdeReader = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
        private string treeViewRecursiv(int id, Stack<int> openPath)
        {
            var fils = from F in GlobalPdeReader.FileAndFolder_View
                       where F.FileInfoID == id
                       select F;
            string retVal = "{\"Item\":\"" + fils.First().Title + "\",";
            retVal += "\"Type\":\"" + (fils.First().FileFlag.Value ? "file" : "folder") + "\",";
            retVal += "\"JSFunction\":\"" + fils.First().JSFunction + "\",";
            retVal += "\"FileInfoId\":\"treeNode_" + fils.First().FileInfoID + "\",";
            if (openPath.Count != 0 && openPath.Peek() == id)
            {
                retVal += "\"Class\":\"open\",";
                openPath.Pop();
            }
            else
                retVal += "\"Class\":\"close\",";
            string child = "";
            var Children = from F in GlobalPdeReader.FileAndFolder_View
                           where F.ParentID == id
                           select F;
            bool first = true;

            foreach (var item in Children)
            {
                if (first)
                {
                    child += treeViewRecursiv(item.FileInfoID, openPath);
                    first = false;
                }
                else
                    child += "," + treeViewRecursiv(item.FileInfoID, openPath);
            }
            if (child == "")
                retVal += "\"ChildItems\":\"\"}";
            else
                retVal += "\"ChildItems\":[" + child + "]}";
            return retVal;

        }
        private Boolean copyPastOnDisk(string sourcePath, string targetPath, string sourceFileName, string DestfileName, Boolean file)
        {


            string sourceFile = System.IO.Path.Combine(sourcePath, sourceFileName);
            string destFile = System.IO.Path.Combine(targetPath, DestfileName);

            if (file)
            {

                //if (!System.IO.Directory.Exists(targetPath))
                //{
                //    System.IO.Directory.CreateDirectory(targetPath);
                //}

                System.IO.File.Copy(sourceFile, destFile, true);
                return true;
            }
            else
            {
                if (System.IO.Directory.Exists(sourcePath))
                {
                    //string[] files = System.IO.Directory.GetFiles(sourcePath);

                    // Copy the files and overwrite destination files if they already exist.
                    string[] files = System.IO.Directory.GetFiles(sourceFile);
                    //  System.IO.Directory.CreateDirectory(destFile);
                    System.IO.Directory.CreateDirectory(destFile);

                    foreach (string s in files)
                    {
                        // Use static Path methods to extract only the file name from the path.
                        string haha;

                        haha = System.IO.Path.GetFileName(s);
                        haha = System.IO.Path.Combine(destFile, haha);
                        // fileName = System.IO.Path.GetFileName(s);
                        //destFile = System.IO.Path.Combine(targetPath, fileName);
                        System.IO.File.Copy(s, haha, true);
                        /// System.IO.Directory.CreateDirectory(sourceFile);



                    }
                    files = System.IO.Directory.GetDirectories(sourceFile);
                    foreach (string s in files)
                    {
                        // Use static Path methods to extract only the file name from the path.
                        string haha;

                        haha = System.IO.Path.GetFileName(s);
                        haha = System.IO.Path.Combine(destFile, haha);
                        System.IO.Directory.CreateDirectory(haha);
                        // fileName = System.IO.Path.GetFileName(s);
                        //destFile = System.IO.Path.Combine(targetPath, fileName);
                        copyPastOnDisk(s, haha, "", "", false);
                        /// System.IO.Directory.CreateDirectory(sourceFile);



                    }

                    return true;
                }
                else
                    return false;

            }
        }
        private Boolean deleteFromDisk(string directoryLocation, string fileName, Boolean file)
        {
            string fileLocation = System.IO.Path.Combine(directoryLocation, fileName);
            if (file)
            {
                // Delete a file by using File class static method...
                if (System.IO.File.Exists(directoryLocation))
                {
                    // Use a try block to catch IOExceptions, to
                    // handle the case of the file already being
                    // opened by another process.

                    try
                    {
                        System.IO.File.Delete(fileLocation);
                        return true;
                    }
                    catch (System.IO.IOException e)
                    {

                        // e.Message();
                        return false;
                    }

                }

                // ...or by using FileInfo instance method.
                System.IO.FileInfo fi = new System.IO.FileInfo(fileLocation);
                try
                {
                    fi.Delete();
                    return true;
                }
                catch (System.IO.IOException e)
                {
                    // e.Message();
                    return false;
                }

                // Delete a directory. Must be writable or empty.
                try
                {
                    System.IO.Directory.Delete(directoryLocation);
                    return true;
                }
                catch (System.IO.IOException e)
                {
                    //e.Message();
                    return false;
                }
                // Delete a directory and all subdirectories with Directory static method...
                if (System.IO.Directory.Exists(directoryLocation))
                {
                    try
                    {
                        System.IO.Directory.Delete(directoryLocation, true);
                        return true;
                    }

                    catch (System.IO.IOException e)
                    {
                        // e.Message();
                        return false;
                    }
                }
            }
            else
            {
                if (System.IO.Directory.Exists(fileLocation))
                {
                    //string[] files = System.IO.Directory.GetFiles(sourcePath);

                    // Copy the files and overwrite destination files if they already exist.
                    string[] fil = System.IO.Directory.GetFiles(fileLocation);
                    //  System.IO.Directory.CreateDirectory(destFile);
                    //  System.IO.Directory.CreateDirectory(destFile);

                    foreach (string s in fil)
                    {
                        // Use static Path methods to extract only the file name from the path.
                        string haha;

                        haha = System.IO.Path.GetFileName(s);
                        haha = System.IO.Path.Combine(fileLocation, haha);
                        // fileName = System.IO.Path.GetFileName(s);
                        //destFile = System.IO.Path.Combine(targetPath, fileName);
                        System.IO.File.Delete(s);
                        /// System.IO.Directory.CreateDirectory(sourceFile);



                    }
                    fil = System.IO.Directory.GetDirectories(fileLocation);
                    foreach (string s in fil)
                    {
                        // Use static Path methods to extract only the file name from the path.
                        string haha;

                        haha = System.IO.Path.GetFileName(s);
                        haha = System.IO.Path.Combine(fileLocation, haha);
                        // System.IO.Directory.CreateDirectory(haha);
                        // fileName = System.IO.Path.GetFileName(s);
                        //destFile = System.IO.Path.Combine(targetPath, fileName);
                        deleteFromDisk(haha, "", false);
                        /// System.IO.Directory.CreateDirectory(sourceFile);



                    }
                    System.IO.Directory.Delete(fileLocation);

                    return true;
                }
                else
                    return false;

            }


        }
        private static List<string> sortBySize(string directry)
        {


            // File names.
            string[] fns = Directory.GetFiles(directry);
            List<string> SBS = new List<string>();

            // Order by size.
            var sort = from fn in fns
                       orderby new FileInfo(fn).Length
                       select fn;

            // List files.
            foreach (string n in sort)
            {

                SBS.Add(n);


            }
            return SBS;

        }
        private static List<string> sortByName(string dir)
        {
            string[] fns = Directory.GetFiles(dir);
            List<string> SBN = new List<string>();

            // Order by name.
            var sort = from fn in fns
                       orderby new FileInfo(fn).Name
                       select fn;

            // List files.
            foreach (string n in sort)
            {

                SBN.Add(n);


            }
            return SBN;
        }
        public void findePath(Stack<int> ids)
        {
            int currentid = ids.Peek();
            if (currentid == 0)
                return;
            var folder = from F in GlobalPdeReader.FileAndFolder_View
                         where F.FileInfoID == currentid
                         select F;
            ids.Push(folder.First().ParentID.Value);
            findePath(ids);
        }
        public void fillAddressStack(Stack<XElement> ids)
        {
            int currentid = int.Parse(ids.Peek().Element("FileInfoID").Value);
            int parentid = int.Parse(ids.Peek().Element("ParentID").Value);
            if (parentid == 0)
                return;
            var folder = from F in GlobalPdeReader.FileAndFolder_View
                         where F.FileInfoID == parentid
                         select F;

            ids.Push(ConvertFileInfoXml(folder.First()));
            fillAddressStack(ids);
        }
        private Paltop_DatabaseLayer.PaltopDatabaseEntities AlterSizePde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
        private void AlterParentSize(int id, int size)
        {
            if (id == 0)
                return;
            var child = (from F in AlterSizePde.FileInfoes
                         where F.FileInfoID == id
                         select F).Single();
            child.Size += size;
            AlterParentSize(child.ParentID.Value, size);

        }

        public string OpenTextFile(int fileId, int userID)
        {
            var textFile = from T in GlobalPdeReader.FileAndFolder_View
                           where T.AccountID == userID && T.FileInfoID == fileId
                           select T;
            string fileAddrea = HttpRuntime.AppDomainAppPath + "fileManager\\" + userID + "\\" + textFile.First().Address + "\\" + textFile.First().Title;
            FileStream fstream = new FileStream(fileAddrea, FileMode.Open, FileAccess.Read);
            StreamReader streamReader = new StreamReader(fstream);
            return streamReader.ReadToEnd();
        }



        public string tempFunction(string name)
        {
            Paltop_DatabaseLayer.PaltopDatabaseEntities pde = new Paltop_DatabaseLayer.PaltopDatabaseEntities();
            var b = pde.FileAndFolder_View.Where(p => p.Title == name);
            var currentPic = b.FirstOrDefault();

            return currentPic.Address;
        }
        public bool addFolderToFileManager(int pid, string DirectoryAddress, int userId)
        {
            DirectoryAddress = HttpRuntime.AppDomainAppPath + DirectoryAddress.Substring(1);
            DirectoryAddress = DirectoryAddress.Replace("/","\\" );
            DirectoryInfo dInfo = new DirectoryInfo(DirectoryAddress);
            return AddFilesToFileManager(CreateNewFolderInside(userId, pid, dInfo.Name), dInfo.FullName, userId);

        }
        public bool AddFilesToFileManager(int fileInfoId, string DirectoryAddress, int userId)
        {
            //not ready yet;
            string[] files = Directory.GetFiles(DirectoryAddress);
            string[] directories = Directory.GetDirectories(DirectoryAddress);
            bool status = false;
            foreach (var item in files)
            {
                FileInfo finfo = new FileInfo(item);

                AddFile(userId, finfo.Name, finfo.Extension.Substring(1), fileInfoId, (int)finfo.Length);
            }
            foreach (var item in directories)
            {
                DirectoryInfo dInfo = new DirectoryInfo(item);
                status = AddFilesToFileManager(CreateNewFolderInside(userId, fileInfoId, dInfo.Name), item, userId);
            }
            return status;
        }

    }
}
